package com.theaf.core.error;

import com.alibaba.dubbo.rpc.RpcContext;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;


/*  *
    * 线程环境
    * @author songwenke
    * @date 2016-2-22
    *
    */
@Component(ThreadContext.NAME)
public class ThreadContext {
	public static final String NAME = "smyw.threadContext";

	private static final ThreadLocal<Context> THREAD_CONTEXT = new ThreadLocal<Context>();

	/**
	 * 线程上下文
	 * 
	 * @author tome
	 *
	 */
	class Context {
		String requestId;
		String clientId;
		String clientIp;
		String userName;
		String token;

		@Override
		public String toString() {
			return "Context [RequestId=" + requestId + ", clientId=" + clientId + ", clientIp=" + clientIp
					+ ", userName=" + userName + ", token=" + token + "]";
		}
	}

	private Context getContext() {
		Context context = THREAD_CONTEXT.get();
		if (null == context) {
			context = new Context();
			THREAD_CONTEXT.set(new Context());
		}
		return context;
	}

	/**
	 * 获取当前线程的请求id
	 * 
	 * @return
	 */
	public String getRequestId() {
		return getContext().requestId;
	}

	/**
	 * 设置当前线程的请求id
	 * 
	 * @return
	 */
	public void setRequestId(String requestId) {
		Context context = getContext();
		context.requestId = requestId;
		THREAD_CONTEXT.set(context);
	}

	/**
	 * 生成当前线程的请求id
	 * 
	 * @return
	 */
	public String generateRequestId() {
		String requestId = getRequestId();
		if (null != requestId) {
			return requestId;
		}

		requestId = System.currentTimeMillis() + "";
		setRequestId(requestId);
		return requestId;
	}

	public String getClientId() {
		Context context = getContext();
		return context.clientId;
	}

	public void setClientId(String clientId) {
		Context context = getContext();
		context.clientId = clientId;
		THREAD_CONTEXT.set(context);
	}

	public String getClientIp() {
		Context context = getContext();
		return context.clientIp;
	}

	public void setClientIp(String clientIp) {
		Context context = getContext();
		context.clientIp = clientIp;
		THREAD_CONTEXT.set(context);
	}

	public String getUserName() {
		Context context = getContext();
		return context.userName;
	}

	public void setUserName(String userName) {
		Context context = getContext();
		context.userName = userName;
		THREAD_CONTEXT.set(context);
	}

	public String getToken() {
		Context context = getContext();
		return context.token;
	}

	public void setToken(String token) {
		Context context = getContext();
		context.token = token;
		THREAD_CONTEXT.set(context);
	}

	public void clear() {
		THREAD_CONTEXT.set(null);
	}

	@Override
    public String toString() {
		return getContext().toString();
	}

	private static final String CONTEXT_SPLIT_CHAR = "@#";
	private static final int CONTEXT_SPLIT_CHAR_MAX=5;
	private static final String CTX_ATTACHMENT_NAME = "_threadCtx";

	/**
	 * 将线程上下文放入dubbo， 有时间再改造优化
	 */
	public void embedDubboAttachment() {
		String s = getContext().requestId + CONTEXT_SPLIT_CHAR;

		s += getContext().userName == null ? " " : getContext().userName;
		s += CONTEXT_SPLIT_CHAR;
		s += getContext().clientIp == null ? " " : getContext().clientIp;
		s += CONTEXT_SPLIT_CHAR;
		s += getContext().clientId == null ? " " : getContext().clientId;
		s += CONTEXT_SPLIT_CHAR;
		s += getContext().token == null ? " " : getContext().token;
		RpcContext.getContext().setAttachment(CTX_ATTACHMENT_NAME, s);
	}

	/**
	 * 将dubbo数据抽取绑定到线程上下文 可以直接取ibvokenantionn里的信息
	 * 
	 * @return
	 * @return
	 */
	public void extractDubboAttachment(String dubboAttachment) {
		if (StringUtils.isEmpty(dubboAttachment)) {
			dubboAttachment = RpcContext.getContext().getAttachment(CTX_ATTACHMENT_NAME);
		}
		if (dubboAttachment != null) {
			String[] ctxArr = dubboAttachment.split(CONTEXT_SPLIT_CHAR);
			if (ctxArr.length >= CONTEXT_SPLIT_CHAR_MAX) {
				this.setClientId(StringUtils.isBlank(ctxArr[3]) ? null : ctxArr[3]);
				this.setClientIp(StringUtils.isBlank(ctxArr[2]) ? null : ctxArr[2]);
				this.setRequestId(ctxArr[0]);
				this.setToken(StringUtils.isBlank(ctxArr[4]) ? null : ctxArr[4]);
				this.setUserName(StringUtils.isBlank(ctxArr[1]) ? null : ctxArr[1]);
			}
		}
	}
}
